package ws;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import netty.util.StartAndStop;
import okhttp3.*;
import okio.ByteString;
import org.apache.commons.lang3.RandomUtils;
import test.PerformanceAnalyze;

import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class OkHttpWsPublicCompress extends StartAndStop {

    static PerformanceAnalyze performanceAnalyze = new PerformanceAnalyze();

    private WebSocket init(String url) {
        OkHttpClient mClient = new OkHttpClient.Builder()
                .readTimeout(30, TimeUnit.SECONDS)//设置读取超时时间
                .writeTimeout(30, TimeUnit.SECONDS)//设置写的超时时间
                .connectTimeout(30, TimeUnit.SECONDS)//设置连接超时时间
                .build();

        //构建一个连接请求对象
        Request request = new Request.Builder().get().url(url).build();

        //开始连接
        return mClient.newWebSocket(request, new WebSocketListener() {
            @Override
            public void onOpen(WebSocket webSocket, Response response) {
                super.onOpen(webSocket, response);
                System.out.println("连接成功, webSocket: " + webSocket);
                System.out.println("连接成功, response: " + webSocket);
            }

            @Override
            public void onMessage(WebSocket webSocket, String text) {
                super.onMessage(webSocket, text);
                performanceAnalyze.meter();

                JSONObject jsonObject = JSON.parseObject(text);
                if ("MergedMessage".equals(jsonObject.getString("type"))) {
                    JSONArray jsonArray = jsonObject.getJSONArray("messageList");
                    for (int i = 0; i < jsonArray.size(); i++) {
                        performanceAnalyze(jsonArray.getJSONObject(i));
                    }
                } else {
                    performanceAnalyze(jsonObject);
                }

            }

            @Override
            public void onMessage(WebSocket webSocket, ByteString bytes) {
                super.onMessage(webSocket, bytes);
                System.out.println("收到消息, webSocket: " + webSocket);
                System.out.println("收到消息, bytes: " + bytes);
            }

            @Override
            public void onClosed(WebSocket webSocket, int code, String reason) {
                super.onClosed(webSocket, code, reason);
                System.out.println("连接关闭..., webSocket: " + webSocket);
                System.out.println("连接关闭..., code" + code);
                System.out.println("连接关闭..., reason" + reason);
            }

            @Override
            public void onFailure(WebSocket webSocket, Throwable throwable, Response response) {
                super.onFailure(webSocket, throwable, response);
                System.out.println("连接失败..., webSocket: " + webSocket);
                throwable.printStackTrace();
                System.out.println("连接失败..., response: " + response);
            }
        });
    }

    private void performanceAnalyze(JSONObject jsonObject) {
        long creationTime = jsonObject.getLongValue("creationTime");
        if (creationTime != 0) {
            performanceAnalyze.delay(System.currentTimeMillis() - creationTime);
        }
    }

    public void start(String url, int size, boolean enableMerger, String channelPrefix, String env) throws IOException {
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(10);

        List<String> topics = JSON.parseArray("[\"orderbook25.BTC-24JUN22-25000-C\",\"orderbook25.BTC-11MAR22-30000-C\",\"orderbook25.BTC-23DEC22-11-P\",\"orderbook25.BTC-25MAR22-35000-C\",\"orderbook25.BTC-25MAR22-18000-C\",\"orderbook25.BTC-25MAR22-185000-C\",\"orderbook25.BTC-24JUN22-300000-C\",\"orderbook25.BTC-25MAR22-35000-P\",\"orderbook25.BTC-24JUN22-90000-P\",\"orderbook25.BTC-23DEC22-11-C\",\"orderbook25.BTC-25MAR22-210000-P\",\"orderbook25.BTC-24JUN22-25000-P\",\"orderbook25.BTC-24JUN22-100000-C\",\"orderbook25.BTC-25MAR22-125000-P\",\"orderbook25.BTC-24JUN22-100000-P\",\"orderbook25.BTC-24JUN22-300000-P\",\"orderbook25.BTC-23DEC22-10001-P\",\"orderbook25.BTC-25MAR22-50000-C\",\"orderbook25.BTC-23DEC22-7-C\",\"orderbook25.BTC-24JUN22-40000-C\",\"orderbook25.BTC-4MAR22-38000-C\",\"orderbook25.BTC-23DEC22-696-P\",\"orderbook25.BTC-29APR22-40000-P\",\"orderbook25.BTC-24JUN22-40000-P\",\"orderbook25.BTC-23DEC22-5565-C\",\"orderbook25.BTC-29APR22-40000-C\",\"orderbook25.BTC-23DEC22-12-P\",\"orderbook25.BTC-23DEC22-5565-P\",\"orderbook25.BTC-23DEC22-696-C\",\"orderbook25.BTC-4MAR22-70000-C\",\"orderbook25.BTC-25MAR22-16000-P\",\"orderbook25.BTC-29APR22-35000-C\",\"orderbook25.BTC-25MAR22-85000-C\",\"orderbook25.BTC-14DEC22-20000-C\",\"orderbook25.BTC-29APR22-30000-P\",\"orderbook25.BTC-23DEC22-12-C\",\"orderbook25.BTC-29APR22-30000-C\",\"orderbook25.BTC-25MAR22-85000-P\",\"orderbook25.BTC-11MAR22-42000-C\",\"orderbook25.BTC-24JUN22-150000-C\",\"orderbook25.BTC-24JUN22-150000-P\",\"orderbook25.BTC-11MAR22-32000-P\",\"orderbook25.BTC-25MAR22-95000-C\",\"orderbook25.BTC-23DEC22-6-C\",\"orderbook25.BTC-24JUN22-15000-C\",\"orderbook25.BTC-23DEC22-6-P\",\"orderbook25.BTC-25MAR22-130000-C\",\"orderbook25.BTC-4MAR22-60000-C\",\"orderbook25.BTC-29APR22-90000-C\",\"orderbook25.BTC-25MAR22-16000-C\",\"orderbook25.BTC-25MAR22-190000-P\",\"orderbook25.BTC-25MAR22-190000-C\",\"orderbook25.BTC-11MAR22-32000-C\",\"orderbook25.BTC-25MAR22-95000-P\",\"orderbook25.BTC-4MAR22-65000-C\",\"orderbook25.BTC-23DEC22-13-C\",\"orderbook25.BTC-25MAR22-90000-C\",\"orderbook25.BTC-25MAR22-200000-C\",\"orderbook25.BTC-4MAR22-50000-C\",\"orderbook25.BTC-24JUN22-80000-C\",\"orderbook25.BTC-24JUN22-80000-P\",\"orderbook25.BTC-23DEC22-9000-C\",\"orderbook25.BTC-30APR22-166-C\",\"orderbook25.BTC-23DEC22-9-C\",\"orderbook25.BTC-23DEC22-20000-C\",\"orderbook25.BTC-23DEC22-1-P\",\"orderbook25.BTC-25MAR22-175000-C\",\"orderbook25.BTC-4MAR22-46000-C\",\"orderbook25.BTC-23DEC22-20000-P\",\"orderbook25.BTC-25MAR22-15000-C\",\"orderbook25.BTC-23DEC22-14-P\",\"orderbook25.BTC-4MAR22-65000-P\",\"orderbook25.BTC-23DEC22-9000-P\",\"orderbook25.BTC-23DEC22-1-C\",\"orderbook25.BTC-23DEC22-8000-P\",\"orderbook25.BTC-25MAR22-220000-C\",\"orderbook25.BTC-23DEC22-14-C\",\"orderbook25.BTC-25MAR22-175000-P\",\"orderbook25.BTC-24JUN22-250000-C\",\"orderbook25.BTC-4MAR22-55000-P\",\"orderbook25.BTC-11MAR22-34000-C\",\"orderbook25.BTC-23DEC22-8000-C\",\"orderbook25.BTC-23DEC22-10000-P\",\"orderbook25.BTC-4MAR22-36000-P\",\"orderbook25.BTC-4MAR22-55000-C\",\"orderbook25.BTC-30APR22-188-C\",\"orderbook25.BTC-23DEC22-8-C\",\"orderbook25.BTC-23DEC22-8-P\",\"orderbook25.BTC-23DEC22-20001-C\",\"orderbook25.BTC-4MAR22-36000-C\",\"orderbook25.BTC-23DEC22-10000-C\",\"orderbook25.BTC-24JUN22-90000-C\",\"orderbook25.BTC-23DEC22-20001-P\",\"orderbook25.BTC-25MAR22-210000-C\",\"orderbook25.BTC-11MAR22-28000-P\",\"orderbook25.BTC-4MAR22-42000-C\",\"orderbook25.BTC-23DEC22-15-C\",\"orderbook25.BTC-11MAR22-45000-P\",\"orderbook25.BTC-29APR22-55000-C\",\"orderbook25.BTC-29APR22-10000-C\",\"orderbook25.BTC-25MAR22-1-C\",\"orderbook25.BTC-23DEC22-90000-P\",\"orderbook25.BTC-23DEC22-100-C\",\"orderbook25.BTC-11MAR22-28000-C\",\"orderbook25.BTC-25MAR22-155000-P\",\"orderbook25.BTC-29APR22-100000-C\",\"orderbook25.BTC-24JUN22-200000-C\",\"orderbook25.BTC-25MAR22-1-P\",\"orderbook25.BTC-4MAR22-44000-P\",\"orderbook25.BTC-11MAR22-45000-C\",\"orderbook25.BTC-29APR22-10000-P\",\"orderbook25.BTC-30APR22-122-C\",\"orderbook25.BTC-25MAR22-20000-P\",\"orderbook25.BTC-23DEC22-3333-C\",\"orderbook25.BTC-15APR22-1-C\",\"orderbook25.BTC-23DEC22-111-C\",\"orderbook25.BTC-23DEC22-3-P\",\"orderbook25.BTC-23DEC22-500-C\",\"orderbook25.BTC-4MAR22-40000-C\",\"orderbook25.BTC-25MAR22-110000-C\",\"orderbook25.BTC-25MAR22-20000-C\",\"orderbook25.BTC-11MAR22-60000-C\",\"orderbook25.BTC-25MAR22-105000-P\",\"orderbook25.BTC-23DEC22-3-C\",\"orderbook25.BTC-25MAR22-105000-C\",\"orderbook25.BTC-29APR22-70000-C\",\"orderbook25.BTC-14DEC22-302-C\",\"orderbook25.BTC-23DEC22-90000-C\",\"orderbook25.BTC-24JUN22-70000-P\",\"orderbook25.BTC-14DEC22-100-P\",\"orderbook25.BTC-4MAR22-40000-P\",\"orderbook25.BTC-25MAR22-165000-C\",\"orderbook25.BTC-23DEC22-30000-C\",\"orderbook25.BTC-23DEC22-222-P\",\"orderbook25.BTC-24JUN22-70000-C\",\"orderbook25.BTC-25MAR22-80000-C\",\"orderbook25.BTC-25MAR22-10000-C\",\"orderbook25.BTC-25MAR22-120000-C\",\"orderbook25.BTC-23DEC22-222-C\",\"orderbook25.BTC-23DEC22-100000-P\",\"orderbook25.BTC-14DEC22-100-C\",\"orderbook25.BTC-30APR22-144-C\",\"orderbook25.BTC-23DEC22-40000-C\",\"orderbook25.BTC-25MAR22-22000-C\",\"orderbook25.BTC-24JUN22-60000-P\",\"orderbook25.BTC-4MAR22-44000-C\",\"orderbook25.BTC-24JUN22-60000-C\",\"orderbook25.BTC-15APR22-2-C\",\"orderbook25.BTC-14DEC22-301-P\",\"orderbook25.BTC-29APR22-45000-C\",\"orderbook25.BTC-23DEC22-555-C\",\"orderbook25.BTC-11MAR22-38000-C\",\"orderbook25.BTC-25MAR22-22000-P\",\"orderbook25.BTC-29APR22-20000-C\",\"orderbook25.BTC-23DEC22-40000-P\",\"orderbook25.BTC-23DEC22-2-C\",\"orderbook25.BTC-23DEC22-54123-C\",\"orderbook25.BTC-25MAR22-70000-C\",\"orderbook25.BTC-25MAR22-155000-C\",\"orderbook25.BTC-14DEC22-301-C\",\"orderbook25.BTC-23DEC22-555-P\",\"orderbook25.BTC-4MAR22-48000-C\",\"orderbook25.BTC-14DEC22-101-P\",\"orderbook25.BTC-25MAR22-115000-C\",\"orderbook25.BTC-29APR22-80000-P\",\"orderbook25.BTC-4MAR22-34000-C\",\"orderbook25.BTC-25MAR22-75000-P\",\"orderbook25.BTC-11MAR22-36000-C\",\"orderbook25.BTC-24JUN22-50000-P\",\"orderbook25.BTC-23DEC22-50000-P\",\"orderbook25.BTC-25MAR22-145000-C\",\"orderbook25.BTC-4MAR22-48000-P\",\"orderbook25.BTC-24JUN22-20000-C\",\"orderbook25.BTC-25MAR22-100000-C\",\"orderbook25.BTC-29APR22-80000-C\",\"orderbook25.BTC-11MAR22-36000-P\",\"orderbook25.BTC-25MAR22-30000-C\",\"orderbook25.BTC-25MAR22-75000-C\",\"orderbook25.BTC-23DEC22-80000-P\",\"orderbook25.BTC-14DEC22-1000-C\",\"orderbook25.BTC-25MAR22-60000-C\",\"orderbook25.BTC-23DEC22-50000-C\",\"orderbook25.BTC-14DEC22-101-C\",\"orderbook25.BTC-24JUN22-50000-C\",\"orderbook25.BTC-24JUN22-35000-C\",\"orderbook25.BTC-14DEC22-1000-P\",\"orderbook25.BTC-25MAR22-45000-C\",\"orderbook25.BTC-23DEC22-5-C\",\"orderbook25.BTC-25MAR22-45000-P\",\"orderbook25.BTC-25MAR22-135000-P\",\"orderbook25.BTC-24JUN22-120000-C\",\"orderbook25.BTC-25MAR22-55000-P\",\"orderbook25.BTC-29APR22-60000-C\",\"orderbook25.BTC-11MAR22-55000-C\",\"orderbook25.BTC-24JUN22-30000-C\",\"orderbook25.BTC-23DEC22-333-C\",\"orderbook25.BTC-25MAR22-135000-C\",\"orderbook25.BTC-25MAR22-40000-C\",\"orderbook25.BTC-25MAR22-2-C\",\"orderbook25.BTC-29APR22-60000-P\",\"orderbook25.BTC-11MAR22-55000-P\",\"orderbook25.BTC-11MAR22-50000-C\",\"orderbook25.BTC-25MAR22-55000-C\",\"orderbook25.BTC-14DEC22-1001-C\",\"orderbook25.BTC-24JUN22-30000-P\",\"orderbook25.BTC-30APR22-100-C\",\"orderbook25.BTC-11MAR22-40000-P\",\"orderbook25.BTC-25MAR22-65000-P\",\"orderbook25.BTC-25MAR22-125000-C\",\"orderbook25.BTC-29APR22-50000-C\",\"orderbook25.BTC-23DEC22-4-P\",\"orderbook25.BTC-23DEC22-70000-C\",\"orderbook25.BTC-29APR22-50000-P\",\"orderbook25.BTC-24JUN22-120000-P\",\"orderbook25.BTC-25MAR22-115000-P\",\"orderbook25.BTC-11MAR22-40000-C\",\"orderbook25.BTC-29APR22-100000-P\",\"orderbook25.BTC-23DEC22-4-C\",\"orderbook25.BTC-25MAR22-65000-C\",\"orderbook25.BTC-23DEC22-70000-P\"]", String.class);

        List<WebSocket> wsList = new LinkedList<>();

        OkHttpWsPublicCompress okHttpWsPublic = new OkHttpWsPublicCompress();

        for (int i = 0; i < size; i++) {
            wsList.add(okHttpWsPublic.init(url));
        }

        for (WebSocket webSocket : wsList) {
            if (enableMerger) {
                webSocket.send("{\"op\":\"enableMerge\",\"id\":\"1645272016000\",\"args\":[{\"mergeWindow\":\"600\"}]}");
            }
//            webSocket.send("{\"op\":\"fuzzySub\",\"id\":\"1645272018000\",\"args\":[\"ticker\"]}");

            // {"op":"subscribe","id":"1645784808000","args":["1"]}
            Map<String, Object> subscribe = new HashMap<>();
            subscribe.put("id", String.valueOf(System.currentTimeMillis()));
            subscribe.put("op", "subscribe");
            List<String> args = new LinkedList<>();
            args.add(topics.get(RandomUtils.nextInt(0, topics.size()-1)));
            subscribe.put("args", args);
            webSocket.send(JSON.toJSONString(subscribe));
        }

        for (WebSocket webSocket : wsList) {
            Map<String, Object> ping = new HashMap<>();
            ping.put("id", String.valueOf(System.currentTimeMillis()));
            ping.put("op", "ping");

            executor.scheduleAtFixedRate(() -> webSocket.send(JSON.toJSONString(ping)), 1, 10, TimeUnit.SECONDS);

//            Map<String, Object> unSubAll = new HashMap<>();
//            unSubAll.put("id", String.valueOf(System.currentTimeMillis()));
//            unSubAll.put("op", "unSubAll");
//            executor.scheduleAtFixedRate(() -> webSocket.send(JSON.toJSONString(unSubAll)), 1, 10, TimeUnit.SECONDS);
//            executor.scheduleAtFixedRate(() -> webSocket.send("{\"op\":\"fuzzySub\",\"id\":\"1645272018000\",\"args\":[\"ticker\"]}"), 1, 10, TimeUnit.SECONDS);

        }
    }

}
